# Unity CommunicationManager Test Client
# PowerShell client supporting Unity handshake protocol
# 
# This script simulates WPF client communication with Unity
# File paths point to Windows Downloads directory:
# - DXF files: %USERPROFILE%\Downloads\sample.dxf
# - GLB files: %USERPROFILE%\Downloads\model.glb

param(
    [string]$PipeName = "UnityWpfPipe",
    [string]$ServerName = ".",
    [int]$TimeoutMs = 10000
)

Write-Host "=== Unity Communication Manager Test Client ===" -ForegroundColor Cyan
Write-Host "Pipe Name: $PipeName" -ForegroundColor White
Write-Host "Server: $ServerName" -ForegroundColor White
Write-Host "Connection Timeout: ${TimeoutMs}ms" -ForegroundColor White
Write-Host ""

# Global variables
$script:pipeClient = $null
$script:streamWriter = $null
$script:streamReader = $null
$script:isConnected = $false

function Connect-ToUnityPipe {
    Write-Host "Connecting to Unity pipe..." -ForegroundColor Yellow
    
    try {
        Add-Type -AssemblyName System.Core
        
        $script:pipeClient = New-Object System.IO.Pipes.NamedPipeClientStream($ServerName, $PipeName)
        $script:pipeClient.Connect($TimeoutMs)
        $script:isConnected = $true
        
        $script:streamWriter = New-Object System.IO.StreamWriter($script:pipeClient)
        $script:streamWriter.AutoFlush = $true
        $script:streamReader = New-Object System.IO.StreamReader($script:pipeClient)
        
        Write-Host "✓ Successfully connected to Unity pipe!" -ForegroundColor Green
        Write-Host "Connection Status: $($script:pipeClient.IsConnected)" -ForegroundColor Green
        Write-Host ""
        
        # Unity handshake protocol
        Write-Host "Executing Unity handshake protocol..." -ForegroundColor Yellow
        
        $unityReady = $script:streamReader.ReadLine()
        Write-Host "Received Unity signal: $unityReady" -ForegroundColor Cyan
        
        if ($unityReady -eq "UNITY_READY") {
            $script:streamWriter.WriteLine("CLIENT_READY")
            Write-Host "Sent client ready confirmation" -ForegroundColor Green
            
            $connectionEstablished = $script:streamReader.ReadLine()
            Write-Host "Connection confirmation: $connectionEstablished" -ForegroundColor Green
        } else {
            Write-Host "Unity ready signal not received, continuing connection..." -ForegroundColor Yellow
        }
        
        Write-Host ""
        return $true
    }
    catch {
        Write-Host "✗ Connection failed: $($_.Exception.Message)" -ForegroundColor Red
        return $false
    }
}

function Send-UnityMessage {
    param([string]$Message)
    
    if (-not $script:isConnected -or -not $script:pipeClient.IsConnected) {
        Write-Host "✗ Connection lost, cannot send message" -ForegroundColor Red
        return $false
    }
    
    try {
        $script:streamWriter.WriteLine($Message)
        Write-Host "→ Sent: '$Message'" -ForegroundColor Green
        
        $responseReceived = $false
        $attempts = 0
        while (-not $responseReceived -and $attempts -lt 20) {
            if ($script:pipeClient.IsConnected -and $script:streamReader.Peek() -ne -1) {
                $response = $script:streamReader.ReadLine()
                if ($response) {
                    Write-Host "← Response: $response" -ForegroundColor Blue
                    $responseReceived = $true
                }
            }
            Start-Sleep -Milliseconds 50
            $attempts++
        }
        
        return $true
    }
    catch {
        Write-Host "✗ Failed to send message: $($_.Exception.Message)" -ForegroundColor Red
        return $false
    }
}

function Send-JsonMessage {
    param(
        [string]$MessageType,
        [string]$Data = "",
        [bool]$RequiresResponse = $false
    )
    
    $message = @{
        messageType = $MessageType
        messageId = [System.Guid]::NewGuid().ToString()
        timestamp = Get-Date -Format "yyyy-MM-ddTHH:mm:ss.fff"
        data = $Data
        requiresResponse = $RequiresResponse
    }
    
    $jsonMessage = $message | ConvertTo-Json -Compress
    Send-UnityMessage $jsonMessage
}

function Test-UnityConnection {
    if ($script:pipeClient -and $script:isConnected) {
        try {
            $status = $script:pipeClient.IsConnected
            Write-Host "Connection status: $status" -ForegroundColor $(if($status){"Green"}else{"Red"})
            return $status
        }
        catch {
            Write-Host "Error checking connection status: $($_.Exception.Message)" -ForegroundColor Red
            return $false
        }
    } else {
        Write-Host "Connection status: Not connected" -ForegroundColor Red
        return $false
    }
}

function Disconnect-FromUnityPipe {
    Write-Host "Disconnecting..." -ForegroundColor Yellow
    
    if ($script:streamWriter) {
        try { $script:streamWriter.Close(); $script:streamWriter.Dispose() } catch { }
        $script:streamWriter = $null
    }
    
    if ($script:streamReader) {
        try { $script:streamReader.Close(); $script:streamReader.Dispose() } catch { }
        $script:streamReader = $null
    }
    
    if ($script:pipeClient) {
        try { $script:pipeClient.Close(); $script:pipeClient.Dispose() } catch { }
        $script:pipeClient = $null
    }
    
    $script:isConnected = $false
    Write-Host "✓ Connection closed" -ForegroundColor Green
}

function Show-UnityHelp {
    Write-Host ""
    Write-Host "Unity Test Client Commands:" -ForegroundColor Cyan
    Write-Host "  ping                 - Send a simple ping message"
    Write-Host "  json-ping            - Send a JSON format ping message"
    Write-Host "  init                 - Send initialization message"
    Write-Host "  load-scene           - Load scene"
    Write-Host "  import-dxf           - Import DXF from Downloads directory"
    Write-Host "  import-glb-direct    - Import GLB in Direct mode from Downloads"
    Write-Host "  import-glb-preview   - Import GLB in Preview mode from Downloads"
    Write-Host "  import-glb-simple    - Import GLB with minimal config (no config object)"
    Write-Host "  status               - Check connection status"
    Write-Host "  test <message>       - Send a test message"
    Write-Host "  help                 - Show this help"
    Write-Host "  exit/quit            - Exit program"
    Write-Host ""
}

try {
    if (-not (Connect-ToUnityPipe)) {
        Write-Host ""
        Write-Host "Connection failed. Please ensure Unity is running and CommunicationManager is started." -ForegroundColor Yellow
        exit 1
    }
    
    Show-UnityHelp
    
    # 显示测试文件路径信息
    $downloadsPath = "$env:USERPROFILE\Downloads"
    Write-Host "Test File Locations:" -ForegroundColor Cyan
    Write-Host "  DXF files: $downloadsPath\sample.dxf" -ForegroundColor White
    Write-Host "  GLB files: $downloadsPath\model.glb" -ForegroundColor White
    Write-Host "  Note: Place your test files in the Downloads directory with these names" -ForegroundColor Yellow
    Write-Host ""
    
    while ($true) {
        $userInput = Read-Host "Unity Test Client"
        
        if ([string]::IsNullOrWhiteSpace($userInput)) {
            continue
        }
        
        $parts = $userInput.Trim().Split(' ', 2)
        $command = $parts[0].ToLower()
        $message = if ($parts.Length -gt 1) { $parts[1] } else { "" }
        
        switch ($command) {
            "exit" { break }
            "quit" { break }
            "help" { Show-UnityHelp }
            "status" { Test-UnityConnection }
            "ping" {
                Send-UnityMessage "ping"
            }
            "json-ping" {
                Send-JsonMessage "ping" "" $true
            }
            "init" {
                $initData = @{
                    unityVersion = "2022.3.61f1c1"
                    projectVersion = "1.0.0"
                    enableDebug = $true
                } | ConvertTo-Json
                
                Send-JsonMessage "init" $initData $true
            }
            "load-scene" {
                $initData = @{
                    sceneId = "test-scene-001"
                    sceneName = "test"
                    description = "test"
                } | ConvertTo-Json
                
                Send-JsonMessage "load-scene" $initData $true
            }
            "import-dxf" {
                $dxfPath = "$env:USERPROFILE\Downloads\sample.dxf"
                Write-Host "Importing DXF from: $dxfPath" -ForegroundColor Yellow
                
                $importData = @{
                    sceneId = "test-scene-001"
                    dxfFilePath = $dxfPath
                    config = @{
                        wallHeight = 3.0
                        wallThickness = 0.2
                        wallAlpha = 1.0
                        scale = 0.01
                        offset = @{ x = 0; y = 0; z = 0 }
                        wallColor = @{ r = 0.7; g = 0.7; b = 0.7; a = 1.0 }
                        generateColliders = $true
                        enableInteraction = $true
                    }
                } | ConvertTo-Json -Depth 5
                
                Send-JsonMessage "import-dxf" $importData $true
            }
            "import-glb-direct" {
                $glbPath = "$env:USERPROFILE\Downloads\model.glb"
                Write-Host "Importing GLB in Direct mode from: $glbPath" -ForegroundColor Yellow
                
                $importData = @{
                    sceneId = "test-scene-001"
                    glbFilePath = $glbPath
                    importMode = "Direct"
                    config = @{
                        position = @{ x = 0; y = 0; z = 0 }
                        rotation = @{ x = 0; y = 0; z = 0 }
                        scale = @{ x = 1; y = 1; z = 1 }
                        category = "furniture"
                        generateColliders = $true
                        enableDrag = $true
                        enableSelection = $true
                        preserveAnimations = $true
                        preserveMaterials = $true
                        preserveTextures = $true
                        enableLightmapping = $false
                        optimizeMeshes = $true
                        overrideMaterial = $null
                    }
                } | ConvertTo-Json -Depth 5
                
                Send-JsonMessage "import-glb" $importData $true
            }
            "import-glb-preview" {
                $glbPath = "$env:USERPROFILE\Downloads\model.glb"
                Write-Host "Importing GLB in Preview mode from: $glbPath" -ForegroundColor Yellow
                
                $importData = @{
                    sceneId = "test-scene-001"
                    glbFilePath = $glbPath
                    importMode = "Preview"
                    config = @{
                        position = @{ x = 2; y = 0; z = 2 }
                        rotation = @{ x = 0; y = 45; z = 0 }
                        scale = @{ x = 1; y = 1; z = 1 }
                        category = "decoration"
                        generateColliders = $true
                        enableDrag = $true
                        enableSelection = $true
                        preserveAnimations = $true
                        preserveMaterials = $true
                        preserveTextures = $true
                        enableLightmapping = $false
                        optimizeMeshes = $true
                        overrideMaterial = $null
                    }
                } | ConvertTo-Json -Depth 5
                
                Send-JsonMessage "import-glb" $importData $true
            }
            "import-glb-simple" {
                $glbPath = "$env:USERPROFILE\Downloads\model.glb"
                Write-Host "Importing GLB with minimal config from: $glbPath" -ForegroundColor Yellow
                
                $importData = @{
                    sceneId = "test-scene-001"
                    glbFilePath = $glbPath
                    importMode = "Direct"
                } | ConvertTo-Json -Depth 3
                
                Send-JsonMessage "import-glb" $importData $true
            }
            "test" {
                if ([string]::IsNullOrWhiteSpace($message)) {
                    Write-Host "Please provide a test message: test <message>" -ForegroundColor Yellow
                } else {
                    Send-UnityMessage $message
                }
            }
            default {
                Send-UnityMessage $userInput
            }
        }
        
        if ($script:isConnected -and $script:pipeClient -and -not $script:pipeClient.IsConnected) {
            Write-Host "⚠ Connection lost detected" -ForegroundColor Yellow
            $script:isConnected = $false
        }
    }
}
catch {
    Write-Host ""
    Write-Host "✗ Error: $($_.Exception.Message)" -ForegroundColor Red
}
finally {
    Disconnect-FromUnityPipe
    Write-Host ""
    Write-Host "Unity Test Client exited" -ForegroundColor Cyan
}

